﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace org.zx.ms.core.Util {
    public class PocoUtil<T> {
        /// <summary>
        /// 
        /// </summary>
        static public T getValue(object objectValue) {
            if (!DBNull.Value.Equals(objectValue)) {
                return (T)objectValue;
            } else {
                return default(T);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        static public T getValue(object objectValue, T defaultValue) {
            if (!DBNull.Value.Equals(objectValue)) {
                return (T)objectValue;
            } else {
                return defaultValue;
            }
        }
        /// <summary>
        /// handle some simple sql
        /// </summary>
        static public string generatePagingSql(string sql, int pageNum, int rowPerPage) {
            //select id, name from table where id > 1 order by create desc
            sql = sql.ToLower();
            int indexFrom = sql.IndexOf("from");
            int indexWhere = sql.IndexOf("where");
            int indexOrderBy = sql.IndexOf("order by");

            if (indexFrom == -1 || indexOrderBy == -1) {
                throw new Exception("sql format error");
            }
            string selectValues = sql.Substring(6, indexFrom - 6);
            string tableName, conditionOuter, conditionInner, primaryTable = "";
            if (indexWhere == -1) {
                tableName = sql.Substring(indexFrom + 4, indexOrderBy - indexFrom - 4);
                conditionOuter = "";
                conditionInner = "";
            } else {
                tableName = sql.Substring(indexFrom + 4, indexWhere - indexFrom - 4);
                conditionOuter = " " + sql.Substring(indexWhere + 5, indexOrderBy - indexWhere - 5) + " and ";
                conditionInner = " where " + sql.Substring(indexWhere + 5, indexOrderBy - indexWhere - 5);
            }
            if (tableName.IndexOf(",") != -1) {
                primaryTable = tableName.Substring(0, tableName.IndexOf(",")) + ".";
            }

            string orderBy = sql.Substring(indexOrderBy + 8);
            string pagingSql = "select top {0} {1} from {2} where {3} {9}id not in "
                                + "(select top {4} {9}id from {5} {6} order by {7}) "
                                + "order by {8}";
            string result = string.Format(pagingSql,
                                        rowPerPage,
                                        selectValues,
                                        tableName,
                                        conditionOuter,
                                        (rowPerPage * (pageNum - 1)),
                                        tableName,
                                        conditionInner,
                                        orderBy,
                                        orderBy,
                                        primaryTable);
            return result;
        }

        /// <summary>
        /// handle some simple sql
        /// </summary>
        static public string generateCountingSql(string sql) {
            //select id, name from table where id > 1 order by create desc
            sql = sql.ToLower();
            int indexFrom = sql.IndexOf("from");
            int indexOrderBy = sql.IndexOf("order by");
            if (indexFrom == -1) {
                throw new Exception("sql format error");
            }
            if (indexOrderBy == -1) {
                indexOrderBy = sql.Length;
            }
            string result = "select count(*) " + sql.Substring(indexFrom, indexOrderBy - indexFrom);
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        static public T CopyPocoObjectContent(object src, ref T dest) {
            //if (src == null || dest == null) return default(T);
            if (src == null) return default(T);
            Type srcType = src.GetType();
            Type destType = typeof(T);
            if (dest == null) {
                dest = (T)Activator.CreateInstance(typeof(T));
            }
            foreach (PropertyInfo p in srcType.GetProperties()) {
                PropertyInfo prop = destType.GetProperty(p.Name);
                if (prop == null) {
                    continue;
                } else if (p.Name.ToLower().IndexOf("id") != -1) {
                    //ignore XXXId properties, include primary key and foreign key
                    //this will bring in some problem if we want copy keys
                    //if that happened, use CopyPocoObjectContent(src, dest, updateFieldList) instead
                    continue;
                } else if (prop.PropertyType.Name.StartsWith("String")) {
                } else if (prop.PropertyType.Name.StartsWith("string")) {
                } else if (prop.PropertyType.Name.StartsWith("Boolean")) {
                } else if (prop.PropertyType.Name.StartsWith("int")) {
                } else if (prop.PropertyType.Name.StartsWith("Int16")) {
                } else if (prop.PropertyType.Name.StartsWith("Int32")) {
                } else if (prop.PropertyType.Name.StartsWith("Byte[]")) {
                } else if (prop.PropertyType.Name.StartsWith("DateTime")) {
                } else {
                    continue;
                }
                prop.SetValue(dest, p.GetValue(src, null), null);
            }//for
            return dest;
        }
        /// <summary>
        /// 
        /// </summary>
        static public T[] CopyPocoObjectArray(object[] src, ref T[] dest) {
            if (src == null) return null;
            dest = new T[src.Length];
            for (int i = 0; i < src.Length; i++) {
                dest[i] = (T)Activator.CreateInstance(typeof(T));
                CopyPocoObjectContent(src[i], ref dest[i]);
            }
            return dest;
        }

    }

    /// <summary>
    /// 
    /// </summary>
    public class PocoUtilTester {
        static public void execute() {
            SourceObject src = new SourceObject() {
                id = 1,
                name = "tester",
                created = DateTime.Now
            };

            Console.WriteLine("\n\n----testing for copy object content----");
            DestObject dest = null;
            PocoUtil<DestObject>.CopyPocoObjectContent(src, ref dest);
            Console.WriteLine("dest_name: " + dest.name);
        }
    }

    public class SourceObject {
        public int id { get; set; }
        public string name { get; set; }
        public DateTime created { get; set; }
    }

    public class DestObject {
        public int id { get; set; }
        public string name { get; set; }
        public DateTime modified { get; set; }
    }
}